package com.***.cache;

import java.util.*;

/**
 * Created by hangli2 on 2017/7/3.
 * Least recently used，最近最少使用
 * <p>
 * 简单的缓存工具类，将数据缓存到内存中，使用lru算法进行缓存
 * 主要用于处理列表中查询用户名，教材出版社等信息，简单的key-value形式的
 * 保证一次获取列表数据中不再频繁的进行请求同样的数据
 * <p>
 * 可以通过cacheTime设置缓存保留时间（单位分钟），保证信息发生变更时可以及时的获取到，cacheTime到期时清空整个缓存map
 * 通过cacheSize设置缓存池大小
 */
public class LRUCache<K, V> {


    //使用LinkedHashMap做缓存池，为啥用这个，想知道的google或百度
    private LinkedHashMap<K, V> map;

    private static final float hashTableLoadFactor = 0.75f;
    //缓存池大小
    private int cacheSize;
    //缓存时间
    private int cacheTime;
    //创建时间
    private long createTime;

    public LRUCache(int cacheSize, int cacheTime) {
        this.cacheSize = cacheSize;
        this.cacheTime = cacheTime;
        int hashTableCapacity = (int) Math.ceil(cacheSize / hashTableLoadFactor) + 1;
        map = new LinkedHashMap<K, V>(hashTableCapacity, hashTableLoadFactor, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
                return size() > LRUCache.this.cacheSize;
            }
        };
        createTime = new Date().getTime();
    }

    /**
     * get(从缓存中取值)
     *
     * @param key 键
     * @return V 返回值
     * @author hangli2
     * @date 2017/7/3
     */
    public synchronized V get(K key) {
        if (timeout()){
            map.clear();
            createTime = new Date().getTime();
        }
        return map.get(key);
    }

    /**
     * put(将值加到缓存里)
     *
     * @param key   键
     * @param value 值
     * @return void
     * @author hangli2
     * @date 2017/7/3
     */
    public synchronized void put(K key, V value) {
        map.put(key, value);
    }

    /**
     * clear(提供一个手动清空的方法)
     *
     * @return void
     * @author hangli2
     * @date 2017/7/3
     */
    public synchronized void clear() {
        map.clear();
    }

    /**
     * usedSize(查询当前已使用大小)
     *
     * @return int 大小
     * @author hangli2
     * @date 2017/7/3
     */
    public synchronized int usedSize() {
        return map.size();
    }

    /**
     * getAll(获取全部值)
     *
     * @return java.util.Collection<java.util.Map.Entry<K,V>>
     * @author hangli2
     * @date 2017/7/3
     */
    public synchronized Collection<Map.Entry<K, V>> getAll() {
        return new ArrayList<Map.Entry<K, V>>(map.entrySet());
    }

    public synchronized boolean timeout(){
        return new Date().getTime() - createTime > cacheTime * 60 * 1000;
    }

    public int getCacheSize() {
        return cacheSize;
    }

    public void setCacheSize(int cacheSize) {
        this.cacheSize = cacheSize;
    }

    public int getCacheTime() {
        return cacheTime;
    }

    public void setCacheTime(int cacheTime) {
        this.cacheTime = cacheTime;
    }
}
